package user

import (
	"context"
	"errors"
	"time"

	"BookStack/internal/domain/events"
	"BookStack/internal/domain/user"
	appErrors "BookStack/pkg/errors"
	"BookStack/pkg/utils"
)

// Service 用户应用服务接口
type Service interface {
	// 注册用户
	Register(ctx context.Context, req RegisterRequest) (*RegisterResponse, error)

	// 登录
	Login(ctx context.Context, req LoginRequest) (*LoginResponse, error)

	// 获取用户信息
	GetProfile(ctx context.Context, id uint) (*ProfileResponse, error)

	// 更新用户信息
	UpdateProfile(ctx context.Context, id uint, req UpdateProfileRequest) error

	// 修改密码
	ChangePassword(ctx context.Context, id uint, req ChangePasswordRequest) error

	// 获取用户列表
	GetUsers(ctx context.Context, page, pageSize int) (*UserListResponse, error)

	// 设置用户角色
	SetRole(ctx context.Context, id uint, role string) error

	// 设置用户状态
	SetStatus(ctx context.Context, id uint, status int) error

	// 创建用户（管理员操作）
	CreateUser(ctx context.Context, req RegisterRequest) (*RegisterResponse, error)

	// 删除用户（管理员操作）
	DeleteUser(ctx context.Context, id uint) error
}

// service 应用层用户服务实现
type service struct {
	userService    user.Service
	eventPublisher events.Publisher
}

// NewService 创建应用层用户服务
func NewService(userService user.Service, eventPublisher events.Publisher) Service {
	return &service{
		userService:    userService,
		eventPublisher: eventPublisher,
	}
}

// Register 实现注册
func (s *service) Register(ctx context.Context, req RegisterRequest) (*RegisterResponse, error) {
	// 调用领域服务进行注册
	newUser, err := s.userService.Register(ctx, req.Username, req.Email, req.Password, req.Nickname)
	if err != nil {
		// 转换领域错误为应用错误
		appErr := &appErrors.AppError{}
		if errors.As(err, &appErr) {
			switch appErr.Code {
			case appErrors.ErrCodeUsernameExists, appErrors.ErrCodeEmailExists:
				return nil, UserAlreadyExists(req.Username)
			case appErrors.ErrCodeUsernameRequired, appErrors.ErrCodeUsernameMinLength, appErrors.ErrCodeUsernameMaxLength:
				return nil, InvalidUsername(req.Username)
			case appErrors.ErrCodeEmailRequired, appErrors.ErrCodeEmailFormat:
				return nil, InvalidEmail(req.Email)
			case appErrors.ErrCodePasswordRequired, appErrors.ErrCodePasswordMinLength, appErrors.ErrCodePasswordMaxLength:
				return nil, InvalidPassword()
			default:
				return nil, DatabaseError(err)
			}
		}
		return nil, DatabaseError(err)
	}

	// 发送用户创建事件
	event := &events.UserCreatedEvent{
		ID:        newUser.ID,
		Username:  newUser.Username,
		Email:     newUser.Email,
		Nickname:  newUser.Nickname,
		Role:      newUser.Role,
		CreatedAt: newUser.CreatedAt,
	}
	s.eventPublisher.AsyncPublish(ctx, events.NewEvent(events.UserCreatedEventType, event))

	// 返回响应
	return &RegisterResponse{
		ID:       newUser.ID,
		Username: newUser.Username,
		Email:    newUser.Email,
		Nickname: newUser.Nickname,
	}, nil
}

// Login 实现登录
func (s *service) Login(ctx context.Context, req LoginRequest) (*LoginResponse, error) {
	// 验证用户
	user, err := s.userService.Authenticate(ctx, req.Username, req.Password)
	if err != nil {
		// 转换领域错误为应用错误
		appErr := &appErrors.AppError{}
		if errors.As(err, &appErr) {
			switch appErr.Code {
			case appErrors.ErrCodeInvalidCredentials:
				return nil, InvalidCredentials()
			case appErrors.ErrCodeUserNotFound:
				return nil, UserNotFound(req.Username)
			default:
				return nil, DatabaseError(err)
			}
		}
		return nil, DatabaseError(err)
	}

	// 返回登录响应
	return &LoginResponse{
		ID:       user.ID,
		Username: user.Username,
		Nickname: user.Nickname,
		Avatar:   user.Avatar,
		Role:     user.Role,
	}, nil
}

// GetProfile 实现获取用户信息
func (s *service) GetProfile(ctx context.Context, id uint) (*ProfileResponse, error) {
	// 获取用户
	user, err := s.userService.GetByID(ctx, id)
	if err != nil {
		// 转换领域错误为应用错误
		appErr := &appErrors.AppError{}
		if errors.As(err, &appErr) && appErr.Code == appErrors.ErrCodeUserNotFound {
			return nil, UserNotFound(id)
		}
		return nil, DatabaseError(err)
	}

	// 返回用户信息
	return &ProfileResponse{
		ID:        user.ID,
		Username:  user.Username,
		Email:     user.Email,
		Nickname:  user.Nickname,
		Avatar:    user.Avatar,
		Role:      user.Role,
		Status:    user.Status,
		CreatedAt: utils.TimeToJSONTime(user.CreatedAt),
	}, nil
}

// UpdateProfile 实现更新用户信息
func (s *service) UpdateProfile(ctx context.Context, id uint, req UpdateProfileRequest) error {
	// 更新用户信息
	if err := s.userService.UpdateProfile(ctx, id, req.Nickname, req.Avatar); err != nil {
		// 转换领域错误为应用错误
		appErr := &appErrors.AppError{}
		if errors.As(err, &appErr) && appErr.Code == appErrors.ErrCodeUserNotFound {
			return UserNotFound(id)
		}
		return DatabaseError(err)
	}

	// 获取更新后的用户信息
	user, err := s.userService.GetByID(ctx, id)
	if err != nil {
		return DatabaseError(err)
	}

	// 发送用户更新事件
	event := &events.UserUpdatedEvent{
		ID:        user.ID,
		Username:  user.Username,
		Nickname:  user.Nickname,
		Avatar:    user.Avatar,
		UpdatedAt: user.UpdatedAt,
	}
	s.eventPublisher.AsyncPublish(ctx, events.NewEvent(events.UserUpdatedEventType, event))

	return nil
}

// ChangePassword 实现修改密码
func (s *service) ChangePassword(ctx context.Context, id uint, req ChangePasswordRequest) error {
	// 修改密码
	if err := s.userService.ChangePassword(ctx, id, req.OldPassword, req.NewPassword); err != nil {
		// 转换领域错误为应用错误
		appErr := &appErrors.AppError{}
		if errors.As(err, &appErr) {
			switch appErr.Code {
			case appErrors.ErrCodeUserNotFound:
				return UserNotFound(id)
			case appErrors.ErrCodeInvalidCredentials:
				return InvalidCredentials()
			case appErrors.ErrCodePasswordMinLength, appErrors.ErrCodePasswordMaxLength:
				return InvalidPassword()
			default:
				return DatabaseError(err)
			}
		}
		return DatabaseError(err)
	}

	// 获取用户信息
	user, err := s.userService.GetByID(ctx, id)
	if err != nil {
		return DatabaseError(err)
	}

	// 发送密码修改事件
	event := &events.UserPasswordChangedEvent{
		ID:        user.ID,
		Username:  user.Username,
		ChangedAt: user.UpdatedAt,
	}
	s.eventPublisher.AsyncPublish(ctx, events.NewEvent(events.UserPasswordChangedType, event))

	return nil
}

// GetUsers 实现获取用户列表
func (s *service) GetUsers(ctx context.Context, page, pageSize int) (*UserListResponse, error) {
	// 获取用户列表
	users, total, err := s.userService.GetUsers(ctx, page, pageSize)
	if err != nil {
		return nil, DatabaseError(err)
	}

	// 转换为响应格式
	items := make([]*UserResponse, 0, len(users))
	for _, u := range users {
		items = append(items, &UserResponse{
			ID:        u.ID,
			Username:  u.Username,
			Email:     u.Email,
			Nickname:  u.Nickname,
			Avatar:    u.Avatar,
			Role:      u.Role,
			Status:    u.Status,
			CreatedAt: utils.TimeToJSONTime(u.CreatedAt),
		})
	}

	return &UserListResponse{
		Total: total,
		Items: items,
	}, nil
}

// SetRole 实现设置用户角色
func (s *service) SetRole(ctx context.Context, id uint, role string) error {
	// 获取用户原始信息
	user, err := s.userService.GetByID(ctx, id)
	if err != nil {
		appErr := &appErrors.AppError{}
		if errors.As(err, &appErr) && appErr.Code == appErrors.ErrCodeUserNotFound {
			return UserNotFound(id)
		}
		return DatabaseError(err)
	}

	// 保存原角色
	previousRole := user.Role

	// 设置角色
	if err := s.userService.SetRole(ctx, id, role); err != nil {
		appErr := &appErrors.AppError{}
		if errors.As(err, &appErr) && appErr.Code == appErrors.ErrCodeValidation {
			return InvalidRole(role)
		}
		return DatabaseError(err)
	}

	// 获取更新后的用户信息
	updatedUser, err := s.userService.GetByID(ctx, id)
	if err != nil {
		return DatabaseError(err)
	}

	// 发送角色变更事件
	event := &events.UserRoleChangedEvent{
		ID:           updatedUser.ID,
		Username:     updatedUser.Username,
		PreviousRole: previousRole,
		CurrentRole:  updatedUser.Role,
		ChangedAt:    updatedUser.UpdatedAt,
	}
	s.eventPublisher.AsyncPublish(ctx, events.NewEvent(events.UserRoleChangedType, event))

	return nil
}

// SetStatus 实现设置用户状态
func (s *service) SetStatus(ctx context.Context, id uint, status int) error {
	// 获取用户原始信息
	user, err := s.userService.GetByID(ctx, id)
	if err != nil {
		appErr := &appErrors.AppError{}
		if errors.As(err, &appErr) && appErr.Code == appErrors.ErrCodeUserNotFound {
			return UserNotFound(id)
		}
		return DatabaseError(err)
	}

	// 保存原状态
	previousStatus := user.Status

	// 设置状态
	if err := s.userService.SetStatus(ctx, id, status); err != nil {
		appErr := &appErrors.AppError{}
		if errors.As(err, &appErr) && appErr.Code == appErrors.ErrCodeInvalidUserStatus {
			return InvalidStatus(status)
		}
		return DatabaseError(err)
	}

	// 获取更新后的用户信息
	updatedUser, err := s.userService.GetByID(ctx, id)
	if err != nil {
		return DatabaseError(err)
	}

	// 发送状态变更事件
	event := &events.UserStatusChangedEvent{
		ID:             updatedUser.ID,
		Username:       updatedUser.Username,
		PreviousStatus: previousStatus,
		CurrentStatus:  updatedUser.Status,
		ChangedAt:      updatedUser.UpdatedAt,
	}
	s.eventPublisher.AsyncPublish(ctx, events.NewEvent(events.UserStatusChangedType, event))

	return nil
}

// CreateUser 实现创建用户（管理员操作）
func (s *service) CreateUser(ctx context.Context, req RegisterRequest) (*RegisterResponse, error) {
	// 调用领域服务进行注册
	newUser, err := s.userService.Register(ctx, req.Username, req.Email, req.Password, req.Nickname)
	if err != nil {
		// 转换领域错误为应用错误
		appErr := &appErrors.AppError{}
		if errors.As(err, &appErr) {
			switch appErr.Code {
			case appErrors.ErrCodeUsernameExists, appErrors.ErrCodeEmailExists:
				return nil, UserAlreadyExists(req.Username)
			case appErrors.ErrCodeUsernameRequired, appErrors.ErrCodeUsernameMinLength, appErrors.ErrCodeUsernameMaxLength:
				return nil, InvalidUsername(req.Username)
			case appErrors.ErrCodeEmailRequired, appErrors.ErrCodeEmailFormat:
				return nil, InvalidEmail(req.Email)
			case appErrors.ErrCodePasswordRequired, appErrors.ErrCodePasswordMinLength, appErrors.ErrCodePasswordMaxLength:
				return nil, InvalidPassword()
			default:
				return nil, DatabaseError(err)
			}
		}
		return nil, DatabaseError(err)
	}

	// 发送用户创建事件
	event := &events.UserCreatedEvent{
		ID:        newUser.ID,
		Username:  newUser.Username,
		Email:     newUser.Email,
		Nickname:  newUser.Nickname,
		Role:      newUser.Role,
		CreatedAt: newUser.CreatedAt,
	}
	s.eventPublisher.AsyncPublish(ctx, events.NewEvent(events.UserCreatedEventType, event))

	// 返回响应
	return &RegisterResponse{
		ID:       newUser.ID,
		Username: newUser.Username,
		Email:    newUser.Email,
		Nickname: newUser.Nickname,
	}, nil
}

// DeleteUser 实现删除用户（管理员操作）
func (s *service) DeleteUser(ctx context.Context, id uint) error {
	// 获取用户信息
	user, err := s.userService.GetByID(ctx, id)
	if err != nil {
		appErr := &appErrors.AppError{}
		if errors.As(err, &appErr) && appErr.Code == appErrors.ErrCodeUserNotFound {
			return UserNotFound(id)
		}
		return DatabaseError(err)
	}

	username := user.Username

	// 调用领域服务删除用户
	if err := s.userService.DeleteUser(ctx, id); err != nil {
		return DatabaseError(err)
	}

	// 发送用户删除事件
	deletedAt, _ := utils.ParseTime(utils.Now())
	event := &events.UserDeletedEvent{
		ID:        id,
		Username:  username,
		DeletedAt: deletedAt,
	}
	s.eventPublisher.AsyncPublish(ctx, events.NewEvent(events.UserDeletedEventType, event))

	return nil
}

// 解析时间字符串为time.Time类型
func parseTime(timeStr string) time.Time {
	t, _ := time.Parse(utils.StandardTimeFormat, timeStr)
	return t
}
